package com.ruoyi.business.sundry.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.business.sundry.service.SysDataScopeFactoryService;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SysDataScopeFactoryServiceImpl implements SysDataScopeFactoryService
{
    @Autowired
    private ISysRoleService sysRoleService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ISysUserService sysUserService;


    /**
     * 逻辑 数据权限 字符串版
     *
     * @param type 0返回用户 1返回部门
     * @return 权限主键合集
     */
    @Override
    public String fnStrDataScope(String type)
    {
        StringJoiner stringJoiner = new StringJoiner(",");
        for (Long l : fnListDataScope(type))
        {
            stringJoiner.add(l.toString());
        }
        return stringJoiner.toString();
    }

    /**
     * 逻辑 数据权限 集合版
     *
     * @param type 0返回用户 1返回部门
     * @return 权限主键合集
     */
    @Override
    public List<Long> fnListDataScope(String type)
    {
        //类型 保底为用户数据
        if (StrUtil.isEmpty(type))
        {
            type = "0";
        }
        boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
        if (admin)
        {
            return new ArrayList<>();
        }
        List<Long> list = new ArrayList<>();
        List<String> roles = fnRoleDataScopoe();

        check(roles, type, list);
        for (String ds : roles)
        {
            if (ds.equals("1"))
            {
                return new ArrayList<>();
            }
            Set<Long> ids = switch (ds)
            {
//                case "1" -> fn1();
                case "2" -> fn2(ds, type);
                case "3" -> fn3(ds, type);
                case "4" -> fn4(ds, type);
                case "5" -> fn5(ds, type);
                default -> new HashSet<>();
            };
            list.addAll(ids);
        }
        return list;
    }

    /**
     * 检测 角色为空
     *
     * @param roles 角色对象
     * @param type  类型
     * @param list  结果集
     */
    public void check(List<String> roles, String type, List<Long> list)
    {
        if (roles.isEmpty())
        {
            Long deptId = SecurityUtils.getDeptId();
            if (type.equals("0"))
            {
                list.add(0, ObjectUtil.isEmpty(deptId) ? 0L : deptId);
            } else
            {
                list.add(0, SecurityUtils.getUserId());
            }
        }
    }

    /**
     * 逻辑过滤 自定数据权限
     *
     * @param ds   角色主键
     * @param type 逻辑类型
     * @return 主键集合
     */
    public Set<Long> fn2(String ds, String type)
    {
        Set<Long> set = new HashSet<>();

        //拼装部门信息
        set.addAll(sysDeptService.selectDeptListByRoleId(Long.valueOf(ds)));
        return fn(set, type);
    }

    /**
     * @param set  主键集合对象-部门主键
     * @param type 逻辑类型
     * @return 主键集合对象
     */
    private Set<Long> fn(Set<Long> set, String type)
    {
        //空部门处理
        if (set.isEmpty())
        {
            set = new HashSet<>();
            set.add(0L);
            return set;
        }

        //部门类型 返回
        if (type.equals("1"))
        {
            return set;
        }

        //拼装 部门信息,获取角色自定义部门
        StringJoiner stringJoiner = new StringJoiner(",");
        for (Long l : set)
        {
            stringJoiner.add(l.toString());
        }

        set = new HashSet<>();
        //拼装 部门人员
        for (SysUser sysUser : sysUserService.listInDeptIds(stringJoiner.toString()))
        {
            set.add(sysUser.getUserId());
        }

        return set;
    }

    /**
     * 逻辑过滤 本部门
     *
     * @param ds   角色主键
     * @param type 逻辑类型
     * @return 主键集合
     */
    public Set<Long> fn3(String ds, String type)
    {
        Set<Long> set = new HashSet<>();

        //拼装部门信息
        set.add(SecurityUtils.getLoginUser().getUser().getDeptId());
        return fn(set, type);
    }

    /**
     * 逻辑过滤 本部门及以下
     *
     * @param ds   角色主键
     * @param type 逻辑类型
     * @return 主键集合
     */
    public Set<Long> fn4(String ds, String type)
    {
        Set<Long> set = new HashSet<>();

        //拼装部门信息
        set.addAll(sysDeptService.listSubset(SecurityUtils.getLoginUser().getUser().getDeptId()));
        return fn(set, type);
    }

    /**
     * 逻辑过滤 仅本人
     *
     * @param ds   角色主键
     * @param type 逻辑类型
     * @return 主键集合
     */
    public Set<Long> fn5(String ds, String type)
    {
        Set<Long> set = new HashSet<>();
        Long deptId = SecurityUtils.getDeptId();

        //拼装部门信息
        if (type.equals("1"))
        {
            //部门校验
            set.add(ObjectUtil.isEmpty(deptId) ? 0L : deptId);
            return set;
        }

        set = new HashSet<>();
        //拼装 部门人员
        set.add(SecurityUtils.getUserId());

        return set;
    }

    /**
     * @return 获取 用户角色集
     */
    public List<String> fnRoleDataScopoe()
    {
        List<String> list = new ArrayList<>();
        for (SysRole role : SecurityUtils.getLoginUser().getUser().getRoles())
        {
            list.add(role.getDataScope());
        }
        return list;
    }
}
